package com.jht.btconnect.fragment;

import android.bluetooth.BluetoothDevice;
import android.bluetooth.BluetoothGatt;
import android.bluetooth.BluetoothGattCallback;
import android.bluetooth.BluetoothGattCharacteristic;
import android.bluetooth.BluetoothGattService;
import android.bluetooth.BluetoothManager;
import android.bluetooth.BluetoothProfile;
import android.content.Context;
import android.os.Bundle;

import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
import androidx.fragment.app.Fragment;

import android.os.Handler;
import android.os.Message;
import android.os.Parcelable;
import android.util.Log;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.ListView;

import com.jht.btconnect.BTApp;
import com.jht.btconnect.R;
import com.jht.btconnect.adapter.BTDeviceLVAdapter;
import com.jht.btconnect.ui.BTDevicesActivity;

import java.util.ArrayList;
import java.util.Collections;
import java.util.List;

import static com.jht.btconnect.ui.BTDevicesActivity.UI_DISCOVER_SERVICES;

/**
 * A simple {@link Fragment} subclass.
 * Use the {@link BTDeviceFragment#newInstance} factory method to
 * create an instance of this fragment.
 */
public class BTDeviceFragment extends Fragment {
    private String TAG = getClass().getSimpleName();
    // TODO: Rename parameter arguments, choose names that match
    // the fragment initialization parameters, e.g. ARG_ITEM_NUMBER
    private static final String ARG_PARAM1 = "param1";
    private static final String ARG_PARAM2 = "param2";
    private int connectionState = STATE_DISCONNECTED;

    private static final int STATE_DISCONNECTED = 0;
    private static final int STATE_CONNECTING = 1;
    private static final int STATE_CONNECTED = 2;
    // TODO: Rename and change types of parameters
    private String mParam1;
    private String mParam2;

    private ListView mLvBtDevices;
    private BTDeviceLVAdapter btDeviceLVAdapter;

    private BTDevicesActivity.UIHandler uiHandler = null;

    public BTDeviceFragment(BTDevicesActivity.UIHandler uiHandler) {
        this.uiHandler = uiHandler;
    }

    /**
     * Use this factory method to create a new instance of
     * this fragment using the provided parameters.
     *
     * @param param1 Parameter 1.
     * @param param2 Parameter 2.
     * @return A new instance of fragment BTDeviceFragment.
     */
    // TODO: Rename and change types and number of parameters
    public static BTDeviceFragment newInstance(String param1, String param2, BTDevicesActivity.UIHandler uiHandler) {
        BTDeviceFragment fragment = new BTDeviceFragment(uiHandler);
        Bundle args = new Bundle();
        args.putString(ARG_PARAM1, param1);
        args.putString(ARG_PARAM2, param2);
        fragment.setArguments(args);
        return fragment;
    }

    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        if (getArguments() != null) {
            mParam1 = getArguments().getString(ARG_PARAM1);
            mParam2 = getArguments().getString(ARG_PARAM2);
        }
    }

    @Override
    public View onCreateView(LayoutInflater inflater, ViewGroup container,
                             Bundle savedInstanceState) {
        return inflater.inflate(R.layout.fragment_bt_device, container, false);
    }

    @Override
    public void onViewCreated(@NonNull View view, @Nullable Bundle savedInstanceState) {
        super.onViewCreated(view, savedInstanceState);
        mLvBtDevices = view.findViewById(R.id.lv_bt_devices);
        btDeviceLVAdapter = new BTDeviceLVAdapter(getActivity(), gattCallback);
        btDeviceLVAdapter.setUIHandler(uiHandler);
        mLvBtDevices.setAdapter(btDeviceLVAdapter);
        mLvBtDevices.setEmptyView(view.findViewById(R.id.empty_view));
    }

    @Override
    public void onResume() {
        super.onResume();
    }

    public void addDevice(BluetoothDevice device) {
        btDeviceLVAdapter.addDevice(device);
    }

    public void initDevice() {
        btDeviceLVAdapter.clearDevicesList();
    }

    public void close() {
        if (bluetoothGatt == null) {
            return;
        }
        bluetoothGatt.close();
        bluetoothGatt = null;
    }

    protected boolean isDeviceConnected(String address) {
        BluetoothManager bm = (BluetoothManager) (BTApp.getAppContext().getSystemService(Context.BLUETOOTH_SERVICE));
        if (bm != null) {
            List<BluetoothDevice> connectedDevices = bm.getConnectedDevices(BluetoothProfile.GATT);
            for (BluetoothDevice connectedDevice : connectedDevices) {
                if (connectedDevice.getAddress().equals(address)) {
                    return true;
                }
            }
        }

        return false;
    }

    private BluetoothGatt bluetoothGatt = null;
    // Various callback methods defined by the BLE API.
    private final BluetoothGattCallback gattCallback = new BluetoothGattCallback() {
        @Override
        public void onConnectionStateChange(BluetoothGatt gatt, int status,
                                            int newState) {
            if (newState == BluetoothProfile.STATE_CONNECTED) {
                BluetoothDevice device = gatt.getDevice();
                connectionState = STATE_CONNECTED;
                bluetoothGatt = gatt;
                Log.d(TAG, "Connected to GATT server.");
                Log.d(TAG, "Attempting to start service discovery:" +
                        bluetoothGatt.discoverServices());

            } else if (newState == BluetoothProfile.STATE_DISCONNECTED) {
                connectionState = STATE_DISCONNECTED;
                Log.d(TAG, "Disconnected from GATT server.");
                close();
            }
        }

        @Override
        // New services discovered
        public void onServicesDiscovered(BluetoothGatt gatt, int status) {
            if (status == BluetoothGatt.GATT_SUCCESS) {
                List<BluetoothGattService> services = bluetoothGatt.getServices();
                ArrayList<BluetoothGattService> services1 = new ArrayList<>(services.size());
                Log.d(TAG, "onServicesDiscovered: services size = " + services.size() + " ; services1.size = " + services1.size());
                for (BluetoothGattService gattService : services) {
                    services1.add(gattService);
                }
                Bundle bundle = new Bundle();
                bundle.putParcelableArrayList("bt_services", services1);
                Message msg = uiHandler.obtainMessage(UI_DISCOVER_SERVICES);
                msg.setData(bundle);
                uiHandler.sendMessage(msg);
            } else {
                Log.w(TAG, "onServicesDiscovered received: " + status);
            }
        }

        @Override
        // Result of a characteristic read operation
        public void onCharacteristicRead(BluetoothGatt gatt,
                                         BluetoothGattCharacteristic characteristic,
                                         int status) {
            if (status == BluetoothGatt.GATT_SUCCESS) {

            }
        }
    };


}
